﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace Dispatcher.Extensions
{
    /// <summary>
    /// Visual Extensions
    /// </summary>
    internal static class VisualExtensions
    {
        /// <summary>
        /// Gets the visual children.
        /// </summary>
        /// <typeparam name="TType">The type of the type.</typeparam>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>The visual children of the dependency object.</returns>
        public static List<TType> GetVisualChildren<TType>(this DependencyObject dependencyObject) where TType : Visual
        {
            var children = new List<TType>();
            var childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
            for (var i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(dependencyObject, i);
                children.AddRange(child.GetVisualChildren<TType>());
                if (child is TType)
                {
                    children.Add((TType)child);
                }
            }

            return children;
        }

        /// <summary>
        /// Gets the visual parents.
        /// </summary>
        /// <typeparam name="TType">The type of the type.</typeparam>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>The visual parents of the dependency object.</returns>
        public static List<TType> GetVisualParents<TType>(this DependencyObject dependencyObject) where TType : Visual
        {
            var parants = new List<TType>();
            var parent = VisualTreeHelper.GetParent(dependencyObject);
            if (parent == null)
            {
                return new List<TType>();
            }

            parants.AddRange(parent.GetVisualParents<TType>());
            if (parent is TType)
            {
                parants.Add((TType)parent);
            }

            return parants;
        }

        /// <summary>
        /// Gets the nearest visual parent.
        /// </summary>
        /// <typeparam name="TType">The type of the type.</typeparam>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>The visual parent of the dependency object.</returns>
        public static TType GetNearestVisualParent<TType>(this DependencyObject dependencyObject) where TType : Visual
        {
            if (dependencyObject == null)
            {
                return null;
            }

            var parent = VisualTreeHelper.GetParent(dependencyObject);
            if (parent is TType)
            {
                return (TType)parent;
            }

            return GetNearestVisualParent<TType>(parent);
        }
    }
}
